package org.pyload.android.client.fragments; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import org.pyload.android.client.R; import org.pyload.android.client.module.Utils; import org.pyload.android.client.pyLoadApp; import org.pyload.android.client.components.ExpandableListFragment; import org.pyload.android.client.components.TabHandler; import org.pyload.android.client.dialogs.FileInfoDialog; import org.pyload.android.client.module.GuiTask; import org.pyload.thrift.Destination; import org.pyload.thrift.DownloadStatus; import org.pyload.thrift.FileData; import org.pyload.thrift.PackageData; import org.pyload.thrift.Pyload.Client; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.util.Log; import android.view.ContextMenu; import android.view.ContextMenu.ContextMenuInfo; import android.view.LayoutInflater; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.BaseExpandableListAdapter; import android.widget.ExpandableListView; import android.widget.ExpandableListView.ExpandableListContextMenuInfo; import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; public abstract class AbstractPackageFragment extends ExpandableListFragment implements TabHandler { /** * Destination, queue = 0, collector = 1, same as in pyLoad Core */ final static int FILEINFO_DIALOG = 0; private final Runnable mUpdateResults = new Runnable() { public void run() { onDataReceived(); } }; private final Comparator<Object> mOrderComparator = new Comparator<Object>() { public int compare(Object a, Object b) { if (a == null && b == null) return 0; else if (a == null) return 1; else if (b == null) return -1; else if (a instanceof PackageData && b instanceof PackageData) return ((Short) ((PackageData) a).order).compareTo(((PackageData) b).order); else if (a instanceof FileData && b instanceof FileData) return ((Short) ((FileData) a).order).compareTo(((FileData) b).order); return 0; } }; protected int dest; private List<PackageData> data; private pyLoadApp app; private Client client; // tab position private int pos = -1; @Override public void onAttach(Activity activity) { super.onAttach(activity); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); app = (pyLoadApp) getActivity().getApplicationContext(); data = new ArrayList<PackageData>(); } @Override public void onViewCreated(View view, Bundle savedInstanceState) { registerForContextMenu(view.findViewById(android.R.id.list)); PackageListAdapter adp = new PackageListAdapter(app, data, R.layout.package_item, R.layout.package_child_item); setListAdapter(adp); } @Override public void onDestroy() { super.onDestroy(); } @Override public boolean onContextItemSelected(MenuItem item) { Log.d("pyLoad", dest + " onContextItemSelected " + item); // filter event und allow to proceed if (!app.isCurrentTab(pos)) return false; ExpandableListContextMenuInfo info = (ExpandableListContextMenuInfo) item .getMenuInfo(); int type = ExpandableListView .getPackedPositionType(info.packedPosition); if (type == ExpandableListView.PACKED_POSITION_TYPE_CHILD) { int groupPos = ExpandableListView .getPackedPositionGroup(info.packedPosition); int childPos = ExpandableListView .getPackedPositionChild(info.packedPosition); final FileData file; try { file = data.get(groupPos).links.get(childPos); } catch (IndexOutOfBoundsException e) { return false; } switch (item.getItemId()) { case R.id.restart: app.addTask(new GuiTask(new Runnable() { public void run() { client = app.getClient(); client.restartFile(file.fid); } }, app.handleSuccess)); break; case R.id.delete: app.addTask(new GuiTask(new Runnable() { public void run() { client = app.getClient(); ArrayList<Integer> fids = new ArrayList<Integer>(); fids.add(file.fid); client.deleteFiles(fids); } }, app.handleSuccess)); break; case R.id.move: Toast.makeText(getActivity(), R.string.cant_move_files, Toast.LENGTH_SHORT).show(); break; default: break; } return true; } else if (type == ExpandableListView.PACKED_POSITION_TYPE_GROUP) { int groupPos = ExpandableListView .getPackedPositionGroup(info.packedPosition); final PackageData pack; try { pack = data.get(groupPos); } catch (IndexOutOfBoundsException e){ return false; // pack does not exists anymore } switch (item.getItemId()) { case R.id.restart: app.addTask(new GuiTask(new Runnable() { public void run() { client = app.getClient(); client.restartPackage(pack.pid); } }, app.handleSuccess)); break; case R.id.delete: app.addTask(new GuiTask(new Runnable() { public void run() { client = app.getClient(); ArrayList<Integer> pids = new ArrayList<Integer>(); pids.add(pack.pid); client.deletePackages(pids); } }, app.handleSuccess)); break; case R.id.move: app.addTask(new GuiTask(new Runnable() { public void run() { client = app.getClient(); Destination newDest; if (dest == 0) { newDest = Destination.Collector; } else { newDest = Destination.Queue; } client.movePackage(newDest, pack.pid); } }, app.handleSuccess)); break; default: break; } return true; } return false; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.package_list, null, false); } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); } @Override public boolean onChildClick(ExpandableListView parent, View v, int group, int child, long id) { PackageData pack; FileData file; try { pack = data.get(group); file = pack.links.get(child); } catch (Exception e) { return true; } FileInfoDialog dialog = FileInfoDialog.newInstance(pack, file); dialog.show(getFragmentManager(), FileInfoDialog.class.getName()); return true; } @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { MenuInflater inflater = getActivity().getMenuInflater(); inflater.inflate(R.menu.package_context_menu, menu); menu.setHeaderTitle(R.string.choose_action); } @Override public void onSelected() { app = (pyLoadApp) getActivity().getApplicationContext(); refresh(); } @Override public void onDeselected() { } @Override public void setPosition(int pos) { this.pos = pos; } public void refresh() { if (!app.hasConnection()) return; app.setProgress(true); GuiTask task = new GuiTask(new Runnable() { public void run() { client = app.getClient(); if (dest == 0) data = client.getQueueData(); else data = client.getCollectorData(); } }, mUpdateResults); app.addTask(task); } protected void onDataReceived() { app.setProgress(false); Collections.sort(data, mOrderComparator); for (PackageData pak : data) Collections.sort(pak.links, mOrderComparator); PackageListAdapter adapter = (PackageListAdapter) getExpandableListAdapter(); adapter.setData(data); } protected void onTaskPerformed() { refresh(); Toast.makeText(getActivity(), app.getString(R.string.success), Toast.LENGTH_SHORT).show(); } } class PackageListAdapter extends BaseExpandableListAdapter { private final int groupRes; private final int childRes; private final LayoutInflater layoutInflater; private List<PackageData> data; public PackageListAdapter(pyLoadApp app, List<PackageData> data, int groupRes, int childRes) { this.data = data; this.groupRes = groupRes; this.childRes = childRes; layoutInflater = (LayoutInflater) app .getSystemService(Context.LAYOUT_INFLATER_SERVICE); } public void setData(List<PackageData> data) { this.data = data; notifyDataSetChanged(); } public int getGroupCount() { return data.size(); } public int getChildrenCount(int group) { return data.get(group).links.size(); } public Object getGroup(int group) { return data.get(group); } public Object getChild(int group, int child) { return data.get(group).links.get(child); } public long getGroupId(int group) { return group; } public long getChildId(int group, int child) { return child; } public boolean hasStableIds() { return false; } public View getGroupView(int group, boolean isExpanded, View convertView, ViewGroup parent) { PackageData pack = data.get(group); if (convertView == null) { convertView = layoutInflater.inflate(groupRes, null); GroupViewHolder holder = new GroupViewHolder(); holder.name = (TextView) convertView.findViewById(R.id.name); holder.progress = (ProgressBar) convertView .findViewById(R.id.package_progress); holder.size = (TextView) convertView.findViewById(R.id.size_stats); holder.links = (TextView) convertView.findViewById(R.id.link_stats); convertView.setTag(holder); } GroupViewHolder holder = (GroupViewHolder) convertView.getTag(); holder.name.setText(pack.name); if (pack.linkstotal == 0) pack.linkstotal = 1; holder.progress.setProgress((pack.linksdone * 100) / pack.links .size()); holder.size.setText(Utils.formatSize(pack.sizedone) + " / " + Utils.formatSize(pack.sizetotal)); holder.links.setText(pack.linksdone + " / " + pack.links.size()); return convertView; } public View getChildView(int group, int child, boolean isLastChild, View convertView, ViewGroup parent) { FileData file = data.get(group).links.get(child); if (file == null) return null; if (convertView == null) { convertView = layoutInflater.inflate(childRes, null); ChildViewHolder holder = new ChildViewHolder(); holder.name = (TextView) convertView.findViewById(R.id.name); holder.status = (TextView) convertView.findViewById(R.id.status); holder.size = (TextView) convertView.findViewById(R.id.size); holder.plugin = (TextView) convertView.findViewById(R.id.plugin); holder.status_icon = (ImageView) convertView .findViewById(R.id.status_icon); convertView.setTag(holder); } ChildViewHolder holder = (ChildViewHolder) convertView.getTag(); // seems to occure according to bug report // no idea why, and what about other data, so returning the view instantly if (file.name == null) { holder.name.setText(R.string.lambda); return convertView; } if (!file.name.equals(holder.name.getText())) holder.name.setText(file.name); holder.status.setText(file.statusmsg); holder.size.setText(Utils.formatSize(file.size)); holder.plugin.setText(file.plugin); if (file.status == DownloadStatus.Failed || file.status == DownloadStatus.Aborted || file.status == DownloadStatus.Offline) { holder.status_icon.setImageResource(R.drawable.stop); } else if (file.status == DownloadStatus.Finished) { holder.status_icon.setImageResource(R.drawable.tick); } else if (file.status == DownloadStatus.Waiting) { holder.status_icon.setImageResource(R.drawable.menu_clock); } else if (file.status == DownloadStatus.Skipped) { holder.status_icon.setImageResource(R.drawable.tag); } else { holder.status_icon.setImageResource(0); } return convertView; } public boolean isChildSelectable(int group, int child) { return true; } static class GroupViewHolder { private TextView name; private ProgressBar progress; private TextView size; private TextView links; } static class ChildViewHolder { private TextView name; private TextView status; private TextView size; private TextView plugin; private ImageView status_icon; } }